/*
 * date: 2009-11-23 
 * author: Maciej Smolenski <jezdnia@gmail.com>
 */
#ifndef _RPC_PING_HPP_
#define _RPC_PING_HPP_

#include "rpc_error.hpp"
#include "rpc_query.hpp"
#include "rpc_common_data.hpp"
#include <sstream>


namespace rpc_query
{

namespace re=rpc_error;

template <typename CT>
class rpc_ping : public rpc_query<CT>
{
	int m_timeout;
public:
	rpc_ping(std::string p_host, long unsigned p_program, long unsigned p_version, int p_timeout) throw (re::rpc_error);
	void operator()(state_t &state) throw (re::rpc_error);
};

template <typename CT>
rpc_ping<CT>::rpc_ping(std::string p_host, long unsigned p_program, long unsigned p_version, int p_timeout) throw (re::rpc_error) : rpc_query<CT>(p_host, p_program, p_version), m_timeout(p_timeout)
{

};

template <typename CT>
void rpc_ping<CT>::operator()(state_t &state) throw (re::rpc_error)
{
	struct pmaplist *iter,*head = NULL;
	struct timeval timeout;

	state = state_off;

	timeout.tv_sec = m_timeout;
	timeout.tv_usec = 0;

	clnt_stat result;
	unsigned long procedure = NULLPROC;
	result = clnt_call(rpc_query<CT>::m_client, procedure, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_void, NULL, timeout);

	switch(result)
	{
		case RPC_SUCCESS:
			state = state_on;
			break;
		default:
			std::ostringstream os;
			os << "rpc_ping clnt_call failed host: " << rpc_query<CT>::m_host << " program: " << rpc_query<CT>::m_program << " version: " << rpc_query<CT>::m_version << "procedure: " << procedure << " error: " << clnt_sperror(rpc_query<CT>::m_client, "");
			throw re::rpc_error(re::make_error_code(result), os.str());
	}

	if (clnt_freeres(rpc_query<CT>::m_client, (xdrproc_t) xdr_void, (caddr_t) NULL)!=1)
	{
		std::ostringstream os;
		os << "rpc_ping clnt_freeres failed host: " << rpc_query<CT>::m_host << " program: " << rpc_query<CT>::m_program << " version: " << rpc_query<CT>::m_version << "procedure: " << procedure;
		throw re::rpc_error(re::make_error_code(RPC_FAILED), os.str());
	}
};

}

#endif
